const { resolve } = require("path")
const cryptoJs = require("./crypto")
const tokenFns = require("./token")

const utils = {
    ...cryptoJs,
    ...tokenFns,
    // promise封装
    toPromise: (fn) => {
        return new Promise(async (resolve, reject) => {
            try {
                const res = await fn();
                resolve(res);
            } catch (err) {
                reject(err);
            }
        })
    },
    // 导出并使用指定文件夹下的所有js文件
    completeRequire: (directoryPath, options = {}) => {
        const fs = require("fs")
        const path = require("path")

        if (!directoryPath) return
        fs.readdir(directoryPath, (err, files) => {
            if (err) {
                console.log("Failed to read directory:", err)
                return
            }
            files.forEach(file => {
                if (path.extname(file) === ".js" && path.basename(file, ".js") !== "index") {
                    const filePath = path.join(directoryPath, file)
                    try {
                        require(filePath)(options)
                    } catch (error) {
                        return
                    }
                }
            })
        })
    },
    // 断言
    myAssert: async (result, res, errMsg = "", status = 400) => {
        if (result && result.type === 'error') {
            result.message = errMsg || result.message;
            console.log('myAssert function error is: ', result);
            res.status(status).send(result)
        } else {
            res.send(result)
        }
    },
    // try catch
    toTryCatch: async fn => {
        try {
            const result = await fn();
            if (typeof result !== 'object') {
                return { result }
            }
            return result;
        } catch (err) {
            console.error('toTryCatch function error is: ', err.message)
            return { type: 'error', message: err.message, database: err.message }
        }
    },

    // 生成随机字符串
    randomString: (len = 32) => {
        const chars = "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678"
        const maxPos = chars.length
        let pwd = ""
        for (let i = 0; i < len; i++) {
            pwd += chars.charAt(Math.floor(Math.random() * maxPos))
        }
        return pwd
    },
    // 获取对象类型
    getType: obj => {
        const type = typeof obj
        if (type !== "object") {
            // 如果为基础类型就返回
            return type
        }
        return Object.prototype.toString.call(obj).replace(/^\[object (\S+)\]$/, "$1")
    },
    // 判断对象是否为空
    isEmptyObject: obj => {
        if (obj && typeof obj === "object" && Object.keys(obj).length === 0) {
            return true
        }
        return false
    },
    /**
     * @description: 检查端口是否被占用，未占用返回true，占用返回false
     * @param {*} port 
     * @returns 
     */
    checkPortInUse: (port) => {
        const net = require('net');
        return new Promise((resolve, reject) => {
            const server = net.createServer();

            server.once('error', (err) => {
                if (err.code === 'EADDRINUSE') {
                    resolve(false);
                } else {
                    reject(err);
                }
            });

            server.once('listening', () => {
                server.close();
                resolve(true);
            });

            server.listen(port);
        });
    },
    flatArrayObject: (data, flatProp, saveParent = false) => {
        const result = [];
        data.forEach((item) => {
            // 判断item中是否存在flatProp属性，且数组长度大于0
            if (item.hasOwnProperty(flatProp) && item[flatProp].length > 0) {
                result.push(...utils.flatArrayObject(item[flatProp], flatProp, saveParent));
                if (saveParent) {
                    item.children.length = 0;
                    result.push(item);
                }
            } else {
                result.push(item);
            }
        });
        return result;
    },
    formatFileSize: (sizeInBytes) => {
        const kiloByte = 1024;
        const fileSizeInKB = sizeInBytes / kiloByte;
        return fileSizeInKB.toFixed(2); // 保留两位小数
    }
}
module.exports = utils